# 车辆到达目的地消失会自动添加车辆
import datetime
import time
import simpla
from traci import TraCIException
import random
import platoonUtils
import scene
import sumo_main
import sumo_utils
from scene._car_config import Car_config
from scene.plexe_enum import Plexe_enum
from constants import KAFKA_HOST, TRAFFIC_FLOW_TOPIC, TRAFFIC_FLOW_TOPIC_WEBGL, VIR_DEVICE_STATUS_TOPIC, \
    CA_VEHICLE_FORMATION_INFORMATION, TRAFFIC_EVENT_TOPIC, MTF_TRAFFIC_FLOW_TOPIC, MTF_TRAFFIC_FLOW_TOPIC_WEBGL,MTF_BAD_WEATHER_TOPIC
import traci.constants as tc
import uuid
from utils import station_util
from utils.station_util import get_station_number, get_edge
import json

sceneInfo_type_dict = {
    "accident": 1,
    "badWeather": 3,
    "construction": 15
}
accident_count = 0
badWeather_count = 0
construction_count = 0
weights = [(1, 0.3), (3, 0.4), (15, 0.3)]
prev_event = None  # 保存上一个周期的场景事件
badWeather_info = []


# 随机仿真
def randomSimulation(rou_cfg, traci, accident, plexe, vehicle_ids, badWeather, BAD_WEATHER_POLYGON_SIGN,
                     bad_weather_polygon, sumo_net_instance, producer, task_id):
    global prev_event, accident_count, badWeather_count, construction_count
    # 获取当前时间
    now = datetime.datetime.now()

    # 定义所需输出格式
    output_format = '%Y-%m-%d %H:%M:%S'

    # 格式化当前时间
    formatted_time = now.strftime(output_format)
    sumo_time = traci.simulation.getCurrentTime() / 1000.0
    ss = sumo_time % rou_cfg['simulationCycle']
    if sumo_time % rou_cfg['simulationCycle'] == 0 or sumo_time == 0:
        new_event = random.choices(population=list(sceneInfo_type_dict.values()), weights=[w[1] for w in weights], k=1)[
            0]
        # 旧事件不为空删除旧事件
        if prev_event is not None:
            if prev_event == sceneInfo_type_dict["badWeather"]:
                # 删除恶劣天气配置
                for badWeather_i in badWeather:
                    polygon_id = BAD_WEATHER_POLYGON_SIGN + str(badWeather_i['frameId'])
                    if polygon_id in bad_weather_polygon:
                        print("删除恶劣天气配置！")
                        # traci.polygon.remove(polygon_id)
                        # del sumo_main.bad_weather_polygon[polygon_id]
                # start_ts = time.time()
                # init_bad_weather(badWeather, BAD_WEATHER_POLYGON_SIGN, bad_weather_polygon, traci,
                #                  sumo_net_instance)
                # badWeather = []
                # badWeather_ts = time.time()
                # print("恶劣天气场景： ", badWeather_ts - start_ts)
                # 处理 badWeather 事件的逻辑


            else:
                # ======================= 事故区场景（车道禁用） =======================
                start_ts = time.time()
                accident_polygon_list = scene.accident.get_accident_polygon_list()
                for accident_polygon in accident_polygon_list:
                    traci.lane.setDisallowed(accident_polygon['polygonId'], [])
                accident_ts = time.time()
                print("事故区场景： ", accident_ts - start_ts)
                # 处理 accident 事件的逻辑
                print("删除事故区！")
        # 判断新旧场景事件是否相同，如果不同则进行逻辑处理
        if new_event != prev_event:
            # 新事件发生
            if new_event == sceneInfo_type_dict["accident"]:
                # ======================= 事故区场景（车道禁用） =======================
                start_ts = time.time()

                accidents = add_accident_area(accident)
                accident_ts = time.time()
                print("事故区场景： ", accident_ts - start_ts)
                # 处理 accident 事件的逻辑
                accident_count += 1
                # 发送消息
                busyAreas = list()
                for accidents_i in accidents:
                    busyArea = {"type": accidents_i['status'], 'polygons': accidents_i['polygons']}
                    busyAreas.append(busyArea)
                    lon = accidents_i['areaPoints'][0][0]
                    lat = accidents_i['areaPoints'][0][1]
                    min_distance, station_info_id = station_util.get_station_number(lon, lat)
                trafficEvent = {"eventType": '5',
                                "eventLocation": station_info_id + '+' + str("{:.2f}".format(min_distance)),
                                "date": formatted_time, 'busyAreas': busyAreas, 'serverWeather': []
                                }

                trafficEvents = list()
                trafficEvents.append(trafficEvent)
                CARoadCombinedEvent = {"taskid": task_id, "date": formatted_time, "trafficData": trafficEvents}
                producer.send(TRAFFIC_EVENT_TOPIC, value=CARoadCombinedEvent, key=task_id)
                print("有车祸事件发生！")
            elif new_event == sceneInfo_type_dict["badWeather"]:
                # ======================= 恶劣天气场景 =======================
                start_ts = time.time()
                init_bad_weather(badWeather, BAD_WEATHER_POLYGON_SIGN, bad_weather_polygon, traci,
                                 sumo_net_instance)
                badWeather_ts = time.time()
                print("恶劣天气场景： ", badWeather_ts - start_ts)
                # 发送消息
                ServerWeathers = list()
                for badWeather_i in badWeather:
                    SituationLL = {"longitude": badWeather_i['lon'], "latitude": badWeather_i['lat']}
                    ServerWeather = {"type": badWeather_i['status'], 'situation': SituationLL,
                                     'radius': badWeather_i['radius']}
                    ServerWeathers.append(ServerWeather)
                    min_distance, station_info_id = station_util.get_station_number(badWeather_i['lon'],
                                                                                    badWeather_i['lat'])
                trafficEvent = {"eventType": '6',
                                "eventLocation": str(station_info_id) + '+' + str("{:.2f}".format(min_distance)),
                                "date": formatted_time,
                                'busyAreas': [], 'serverWeather': ServerWeathers
                                }

                trafficEvents = list()
                trafficEvents.append(trafficEvent)
                CARoadCombinedEvent = {"taskid": task_id, "date": formatted_time, "trafficData": trafficEvents}
                producer.send(TRAFFIC_EVENT_TOPIC, value=CARoadCombinedEvent, key=task_id)
                # 处理 badWeather 事件的逻辑
                badWeather_count += 1
                print("有恶劣天气事件发生！")
            elif new_event == sceneInfo_type_dict["construction"]:
                # ======================= 施工区场景（车道禁用） =======================
                start_ts = time.time()

                add_construction_area(accident)

                accident_ts = time.time()
                print("道路施工场景： ", accident_ts - start_ts)
                # 处理 accident 事件的逻辑
                construction_count += 1
                print("有道路施工事件发生！")
            else:
                # 处理 construction 事件的逻辑
                start_ts = time.time()
                accident_polygon_list = scene.accident.get_accident_polygon_list()
                for accident_polygon in accident_polygon_list:
                    traci.lane.setDisallowed(accident_polygon['polygonId'], [])
                accident_ts = time.time()
                print("道路施工场景： ", accident_ts - start_ts)

                print("有道路施工事件发生！")

            prev_event = new_event  # 更换事件
        else:
            # 新旧场景事件相同，不进行处理
            print("当前无新事件。")
    else:
        return None


# 车辆到达目的地消失会自动添加车辆
def veh_arrive_automatic_add(traci, platoonSwitch, rou_cfg, plexe, sumo_net_instance):
    # 获取到达车辆列表
    colliding_vehicles_number = traci.simulation.getSubscriptionResults()
    # 车辆到达目的地消失会自动添加车辆
    arrived_vehicles = colliding_vehicles_number[tc.VAR_ARRIVED_VEHICLES_NUMBER]
    arrived_vehicles_ids = colliding_vehicles_number[tc.VAR_ARRIVED_VEHICLES_IDS]
    if arrived_vehicles > 0:
        if Plexe_enum.LEAD.value in arrived_vehicles_ids or Plexe_enum.FOLLOW_ONE.value in arrived_vehicles_ids or Plexe_enum.FOLLOW_TWO.value \
                in arrived_vehicles_ids or Plexe_enum.FOLLOW_THREE.value in arrived_vehicles_ids:
            # 判断编队车辆上是否有其他车辆
            vehicle_ids = traci.lane.getLastStepVehicleIDs('-294.0.00_3')
            try:
                ids = traci.vehicle.getIDList()
                if Plexe_enum.LEAD.value in ids:
                    traci.vehicle.remove(Plexe_enum.LEAD.value)
                if Plexe_enum.FOLLOW_ONE.value in ids:
                    traci.vehicle.remove(Plexe_enum.FOLLOW_ONE.value)
                if Plexe_enum.FOLLOW_TWO.value in ids:
                    traci.vehicle.remove(Plexe_enum.FOLLOW_TWO.value)
                if Plexe_enum.FOLLOW_THREE.value in ids:
                    traci.vehicle.remove(Plexe_enum.FOLLOW_THREE.value)
            except TraCIException as e:
                print('车辆到达目的地消失会自动添加车辆: ', str(e))
            # print('veh_id:', veh_id)
            if len(vehicle_ids) == 0:
                topology = {}
                platoonSwitch['type'] = rou_cfg['type']
                topology = platoonUtils.add_vehicles(plexe, platoonUtils.N_VEHICLES, 1, 90, platoonSwitch,
                                                     real_engine=False)
                sumo_main.topology = topology
        else:
            sumo_main.arrived_depart['count'] = arrived_vehicles
            sumo_utils.add_vehicle(sumo_main.arrived_depart, sumo_net_instance)


# 混合交通流车辆到达目的地消失会自动添加车辆
def MTF_veh_arrive_automatic_add(traci, sumo_net_instance):
    # 获取到达车辆列表
    colliding_vehicles_number = traci.simulation.getSubscriptionResults()
    # 车辆到达目的地消失会自动添加车辆
    arrived_vehicles = colliding_vehicles_number[tc.VAR_ARRIVED_VEHICLES_NUMBER]
    arrived_vehicles_ids = colliding_vehicles_number[tc.VAR_ARRIVED_VEHICLES_IDS]
    if arrived_vehicles > 0:
        sumo_main.arrived_depart['count'] = arrived_vehicles
        # sumo_utils.MTF_add_vehicle(arrived_vehicles_ids,sumo_main.depart_info, sumo_net_instance)
        sumo_utils.MTF_add_vehicle_disappear(arrived_vehicles_ids, sumo_main.depart_info)


# 添加车辆
def add_vehicles(car_config: list, sumo_net_instance, platoonSwitch, rou_cfg, plexe, producer, userId, task_id,
                 resource, leader_ids, start_ts):
    # 普通车辆发车点
    if car_config is not None and len(car_config) > 0:
        for i in range(len(car_config)):
            if car_config[i] is not None and car_config[i].depart is not None:
                sumo_utils.add_vehicle(car_config[i].depart, sumo_net_instance)
                sumo_main.arrived_depart = car_config[i].depart

    #  编队车辆
    if 'status' in platoonSwitch and platoonSwitch['status'] == 0:
        platoonSwitch['type'] = rou_cfg['type']
        topology = platoonUtils.add_vehicles(plexe, platoonUtils.N_VEHICLES, 1, 90, platoonSwitch,
                                             real_engine=False)
        sumo_main.topology = topology
        if platoonUtils.route_start is not None and platoonUtils.route_end is not None:
            start_shapes = sumo_net_instance.getEdge(platoonUtils.route_start).getShape()
            end_shapes = sumo_net_instance.getEdge(platoonUtils.route_end).getShape()
            start_lon, start_lat = sumo_net_instance.convertXY2LonLat(start_shapes[0][0], start_shapes[0][1])
            end_lon, end_lat = sumo_net_instance.convertXY2LonLat(end_shapes[0][0], end_shapes[0][1])
            start_min_distance, start_station_info_id = get_station_number(start_lon, start_lat)
            end_min_distance, end_station_info_id, = get_station_number(end_lon, end_lat)
            key = str(userId) + '_' + str(task_id) + '_' + str(resource)
            vehicleFormationInformation = {"formationId": 'V', "fleetNavigationVehicleId": Plexe_enum.LEAD.value,
                                           "fleetNavigationVehicleSpeed": 30,
                                           "formationDestination": end_station_info_id + '+' + str(
                                               int(end_min_distance)),
                                           "formationSplitPoint": start_station_info_id + '+' + str(
                                               int(start_min_distance)), "fleetMemberVehicleNumber": leader_ids}
            result = {"timeStamp": str(start_ts),
                      "globalTimeStamp": str(start_ts), "taskid": key,
                      "vehicleFormationInformation": vehicleFormationInformation}
            print(result)
            producer.send(CA_VEHICLE_FORMATION_INFORMATION, value=result, key=key)
        platoonSwitch['status'] = '1'
        # # ======================= 应急车道 =======================


# 混合交通流添加车辆
def MTF_add_vehicles(car_config: list, sumo_net_instance):
    # 普通车辆发车点
    if car_config is not None and len(car_config) > 0:
        for i in range(len(car_config)):
            if car_config[i] is not None and car_config[i].depart is not None:
                sumo_utils.MTF_add_vehicle(car_config[i].route, car_config[i].depart)
                # sumo_utils.add_vehicle( car_config[i].depart, sumo_net_instance)
                sumo_main.arrived_depart = car_config[i].depart


def init_emergency_line(emergencyLane, frame_emergencyLaneConfig, traci, sumo_net_instance, tl_ids):
    if len(emergencyLane) > 0 and emergencyLane is not None:
        frameId = emergencyLane['frameId']
        # 全局变量emergencyLaneConfig不为空：已添加配置
        emergencyLane1 = frame_emergencyLaneConfig[frameId]['emergencyLane']
        start_edge_id, start_pos, start_lane_index = traci.simulation.convertRoad(emergencyLane1[0]['lon'],
                                                                                  emergencyLane1[0]['lat'],
                                                                                  True)
        end_edge_id, end_pos, end_lane_index = traci.simulation.convertRoad(emergencyLane1[1]['lon'],
                                                                            emergencyLane1[1]['lat'],
                                                                            True)

        # sumo_net_instance.getTLS()
        if float(start_edge_id.split(".", 1)[0] + "." + start_edge_id.split(".", 1)[1][:1]) > float(
                end_edge_id.split(".", 1)[0] + "." + end_edge_id.split(".", 1)[1][:1]):
            start_edge = sumo_net_instance.getEdge(start_edge_id)
            end_edge = sumo_net_instance.getEdge(end_edge_id)
        else:
            start_edge = sumo_net_instance.getEdge(end_edge_id)
            end_edge = sumo_net_instance.getEdge(start_edge_id)
        message = sumo_utils.initEmergencyLaneConfig(start_edge, end_edge, tl_ids)
        return emergencyLane
    # 匝道管控


def init_ramp_control(vir_ramp_light, traci):
    if vir_ramp_light == 1:
        traci.trafficlight.setRedYellowGreenState("gneJ0", "G")
        # print(
        #     "绿灯+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++")
    else:
        traci.trafficlight.setRedYellowGreenState("gneJ0", "r")
        # print("红灯+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++")
    # ======================= 添加匝道管控设置
    # if rampControl:
    #     rampControlNum = rampControl['rampControlNum']
    #     sumo_utils.addRampControl(vehicle_ids, rampControlNum)
    # ramp_ts = time.time()
    # print("匝道管控时间戳", bad_weather_ts, ramp_ts, ramp_ts - bad_weather_ts)
    # ======================= 匝道通行灯控制 =======================
    # if HttpInterface.trafficLight == 1:
    #     traci.trafficlight.setRedYellowGreenState("gneJ0", "G")
    # elif HttpInterface.trafficLight == 2:
    #     traci.trafficlight.setRedYellowGreenState("gneJ0", "r")


def MTF_init_ramp_control(vir_ramp_light, traci):

    if vir_ramp_light == 1:
        if traci.trafficlight.getRedYellowGreenState("694") != "GGG":
            print("配置匝道管控场景", "GG")
        traci.trafficlight.setRedYellowGreenState("694", "GGG")
        # print(
        #     "绿灯+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++")
    else:
        if traci.trafficlight.getRedYellowGreenState("694") != "rrr":
            print("配置匝道管控场景", "rr")
        traci.trafficlight.setRedYellowGreenState("694", "rrr")


def control_emergency_line(emergency_dict, frame_emergencyLaneControl, sumo_net_instance, tl_ids):
    if len(emergency_dict) > 0:

        for emergency_dict_i_key, emergency_dict_i_value in emergency_dict.items():

            edgeids = frame_emergencyLaneControl[emergency_dict_i_key]['edgeids']
            for edge_id in edgeids:
                edge = sumo_net_instance.getEdge(edge_id)
                edge = sumo_utils.findNewEdge(edge)
                sumo_utils.controlEmergencyLane(emergency_dict_i_value['emergencyLight'], edge, tl_ids)


# ======================= 专用车道 =======================
def init_specialLane(specialLane, frame_emergencyLaneConfig, traci, sumo_net_instance):
    # 创建主路限速场景的专用车道
    # if HttpInterface.exclusiveLaneConfig is not None:
    if len(specialLane) > 0 and specialLane is not None:
        frameId = specialLane['frameId']
        # 全局变量emergencyLaneConfig不为空：已添加配置
        specialLane1 = frame_emergencyLaneConfig[frameId]['specialLane']

        start_edge_id, start_pos, start_lane_index = traci.simulation.convertRoad(specialLane1[0]['lon'],
                                                                                  specialLane1[0]['lat'],
                                                                                  True)
        end_edge_id, end_pos, end_lane_index = traci.simulation.convertRoad(specialLane1[1]['lon'],
                                                                            specialLane1[1]['lat'],
                                                                            True)
        tlss = sumo_net_instance.getTrafficLights()
        start_edge = sumo_net_instance.getEdge(start_edge_id)
        end_edge = sumo_net_instance.getEdge(end_edge_id)
        message = sumo_utils.initExclusiveLaneConfig(start_edge, end_edge, tlss)
        return specialLane
    # 控制专用车道


def control_specialLane(special_dict, frame_emergencyLaneControl, sumo_net_instance, tl_ids):
    if special_dict is not None and len(special_dict) > 0:
        # temp_control = HttpInterface.exclusiveLaneControl
        # HttpInterface.exclusiveLaneControl = None
        for special_dict_i_key, special_dict_i_value in special_dict.items():
            edgeids = frame_emergencyLaneControl[special_dict_i_key]['edgeids']
            for edge_id in edgeids:
                edge = sumo_net_instance.getEdge(edge_id)
                edge = sumo_utils.findNewEdge(edge)
                sumo_utils.controlExclusiveLane(special_dict_i_value['specialLight'], edge, tl_ids)


# ======================= 主路限速场景 =======================
def init_mainRoad_speedLimit(SPEED_LIMIT_SIGN, speed_limit_area_point_list, SPEED_LIMIT_POLYGON_SIGN, limit_polygon,
                             sumo_net_instance, traci, speed_limit_point_list, speed_limit_list):
    # 设置限速场景区域监控  主路限速通过json获取数据 rateLimiting
    if SPEED_LIMIT_SIGN:
        # print("speed_limit_area_point_list",speed_limit_area_point_list)
        for i in range(len(speed_limit_area_point_list)):
            if len(speed_limit_area_point_list[i]) > 0 and SPEED_LIMIT_POLYGON_SIGN not in limit_polygon:
                print("配置主路限速场景", "speed_limit_area_point_list", speed_limit_area_point_list, "limit_polygon",
                      limit_polygon)
                area_pos = list()
                for point in speed_limit_area_point_list[i]:
                    # area_pos.append(traci.simulation.convertGeo(point[1], point[0], True))
                    area_pos.append(sumo_utils.latAndLonConversionXY(sumo_net_instance, point))
                limit_polygon[SPEED_LIMIT_POLYGON_SIGN] = area_pos
                traci.polygon.add(SPEED_LIMIT_POLYGON_SIGN, area_pos, (1, 1, 1))
                traci.polygon.subscribeContext(SPEED_LIMIT_POLYGON_SIGN, tc.CMD_GET_VEHICLE_VARIABLE, 20,
                                               [tc.VAR_SPEED, tc.VAR_DECEL, tc.VAR_DISTANCE, tc.VAR_TYPE,
                                                tc.VAR_POSITION])
        # 限速场景区域车辆行为控制
        vehicles = traci.polygon.getContextSubscriptionResults(SPEED_LIMIT_POLYGON_SIGN)

        for i in range(len(speed_limit_point_list)):
            if vehicles and speed_limit_point_list[i]:
                start_time = time.time()
                sumo_utils.is_point_in_area(vehicles, speed_limit_point_list[i], speed_limit_list[i])
                end_time = time.time()
                # print("限速+++++++++++++++++++++++++++++++++++++++++：", end_time - start_time)
    # limit_ts = time.time()
    # print("发车时间戳", car_ts, limit_ts, limit_ts - car_ts)


# ======================= 事故区场景（车道禁用） =======================
def init_accident(accident, plexe, vehicle_ids):
    # 设置事故区域监控 通过json控制
    for i in range(len(accident)):
        sumo_utils.add_accident_area(accident[i])

    # if HttpInterface.accident:
    #     sumo_utils.add_accident()
    # # 事故区控制
    # if HttpInterface.accidentControl:
    # sumo_utils.control_accident()
    return accident
    # 进入事故区
    # in_accident_veh_list = sumo_utils.in_accident_area(plexe)
    # 离开事故区
    # sumo_utils.out_accident_area(in_accident_veh_list, vehicle_ids)
    # accident_ts = time.time()
    # print("事故区时间戳", limit_ts, accident_ts, accident_ts - limit_ts)


def add_accident_area(accident):
    accidents = list()
    for i in range(len(accident)):
        if accident[i]['status'] == 0:
            accidents.append(accident[i])
            sumo_utils.add_accident_area(accident[i])
    return accidents


def add_construction_area(accident):
    for i in range(len(accident)):
        if accident[i]['status'] == 1:
            sumo_utils.add_accident_area(accident[i])


# ======================= 恶劣天气场景 =======================
def init_bad_weather(badWeather, BAD_WEATHER_POLYGON_SIGN, bad_weather_polygon, traci, sumo_net_instance):
    # 增加恶劣天气配置
    # if HttpInterface.bad_weather_config:
    if badWeather is not None and len(badWeather) > 0 and 'speed' not in badWeather:
        for badWeather_i in badWeather:
            polygon_id = BAD_WEATHER_POLYGON_SIGN + badWeather_i['frameId']
            if polygon_id in bad_weather_polygon:
                traci.polygon.remove(polygon_id)
                del bad_weather_polygon[polygon_id]

            # x, y = traci.simulation.convertGeo(temp_bw_config['point'][1], temp_bw_config['point'][0], True)
            # x, y = sumo_utils.latAndLonConversionXY(sumo_net_instance, temp_bw_config['point'])
            x, y = sumo_net_instance.convertLonLat2XY(badWeather_i['lon'], badWeather_i['lat'])

            traci.polygon.add(polygon_id, [(x, y), (x + 0.1, y), (x + 0.1, y + 0.1), (x, y + 0.1)], (1, 0, 1))
            traci.polygon.subscribeContext(polygon_id, tc.CMD_GET_VEHICLE_VARIABLE, 35,
                                           [tc.VAR_SPEED, tc.VAR_DECEL, tc.VAR_TYPE, tc.VAR_POSITION,
                                            tc.VAR_ACCELERATION])
            bad_weather_polygon[polygon_id] = {
                'points': {'lon': badWeather_i['lon'], 'lat': badWeather_i['lat']},
                'speedLimit': badWeather_i['speed'],
                'radius': badWeather_i['radius']}

    # 删除恶劣天气配置
    # if HttpInterface.del_bad_weather_param:
    #     temp_bw_del_id = HttpInterface.del_bad_weather_param
    #     HttpInterface.del_bad_weather_param = None
    #     polygon_id = BAD_WEATHER_POLYGON_SIGN + str(temp_bw_del_id)
    #     if polygon_id in bad_weather_polygon:
    #         traci.polygon.remove(polygon_id)
    #         del bad_weather_polygon[polygon_id]
    # 进入恶劣天气区
    bw_veh_list = list()
    if bad_weather_polygon:
        for bw_id in bad_weather_polygon.keys():
            result = dict(traci.polygon.getContextSubscriptionResults(bw_id))
            if len(result) > 0:
                # print("===================== bad weather area %s =====================" % bw_id)
                for veh_id in result.keys():
                    if veh_id not in bw_veh_list:
                        bw_veh_list.append(veh_id)
                sumo_utils.in_bw_area(result, bad_weather_polygon[bw_id])
    # 离开恶劣天气区
    sumo_utils.out_bw_area(bw_veh_list)
    # bad_weather_ts = time.time()
    # print("恶劣天气时间戳", accident_ts, bad_weather_ts, bad_weather_ts - accident_ts)


# ======================= 恶劣天气场景 =======================
def MTF_init_bad_weather(badWeather, BAD_WEATHER_POLYGON_SIGN, bad_weather_polygon, traci, sumo_net_instance,producer,userId,
                                                       task_id,resource):
    global badWeather_info
    """
    badWeather:前端传过来的天气信息{'frameId': 'down-02', 'lon': 108.894957, 'lat': 34.37308, 'radius': 20, 'status': 1, 'speed': 40}
    BAD_WEATHER_POLYGON_SIGN：天气区域的key
    bad_weather_polygon:'BAD_WEATHER_POLYGON_down-02':{'points': {'lon': 108.894957, 'lat': 34.37308}, 'speedLimit': 40, 'radius': 20}
    """
    # 增加恶劣天气配置
    # if HttpInterface.bad_weather_config:
    if badWeather is not None and len(badWeather) > 0:
        for badWeather_i in badWeather:

            polygon_id = BAD_WEATHER_POLYGON_SIGN + badWeather_i['frameId']
            # 如果新的恶劣天气配置与历史配置一致，则删除历史配置
            if polygon_id in bad_weather_polygon:
                traci.polygon.remove(polygon_id)
                del bad_weather_polygon[polygon_id]
                del badWeather_info[polygon_id]

            x, y = sumo_net_instance.convertLonLat2XY(badWeather_i['lon'], badWeather_i['lat'])
            traci.polygon.add(polygon_id, [(x, y), (x + 0.1, y), (x + 0.1, y + 0.1), (x, y + 0.1)], (1, 0, 1))
            # 实例中的35，这是一个浮点数，通常用来指定距离，表示只订阅距离指定对象一定距离内的其他对象的信息
            traci.polygon.subscribeContext(polygon_id, tc.CMD_GET_VEHICLE_VARIABLE, badWeather_i['radius'],
                                           [tc.VAR_SPEED, tc.VAR_DECEL, tc.VAR_TYPE, tc.VAR_POSITION,
                                            tc.VAR_ACCELERATION])

            bad_weather_polygon[polygon_id] = {
                'points': {'lon': badWeather_i['lon'], 'lat': badWeather_i['lat']},
                'speedLimit': badWeather_i['speed'],
                'radius': badWeather_i['radius'],
                "delayTime": int(time.time()) + int(badWeather_i['delayTime'])}
            print("配置天气",bad_weather_polygon[polygon_id])

    # 进入恶劣天气区
    bw_veh_list = list()
    if bad_weather_polygon:
        for bw_id in bad_weather_polygon.keys():

            if int(time.time()) >= bad_weather_polygon[bw_id]["delayTime"]:

                # print("!!!!!!!!!!!!!!!!!!!!!!!!!!!",int(time.time()) ,bad_weather_polygon[bw_id]["delayTime"])
                if bw_id not in badWeather_info:
                    MTF_send_kafka_weather_message(producer,bad_weather_polygon[bw_id],userId,task_id,resource)
                    badWeather_info.append(bw_id)
                result = dict(traci.polygon.getContextSubscriptionResults(bw_id))
                if len(result) > 0:
                    # print("===================== bad weather area %s =====================" % bw_id)
                    for veh_id in result.keys():
                        if veh_id not in bw_veh_list:
                            bw_veh_list.append(veh_id)
                    sumo_utils.MTF_in_bw_area(result, bad_weather_polygon[bw_id])
                sumo_utils.MTF_out_bw_area(list(result.keys()))

    # 离开恶劣天气区

    # bad_weather_ts = time.time()
    # print("恶劣天气时间戳", accident_ts, bad_weather_ts, bad_weather_ts - accident_ts)


# ======================= 发送数据封装 =======================
def send_kafka_message(global_vehicles, vtype, sumo_net_instance, traci, userId, task_id, resource, start_ts, producer):
    car_list = list()
    for vehicle_id, veh_info in dict(global_vehicles).items():

        # 编队车辆禁止变道
        # if 'v.0.0' in vehicle_ids:
        #     plexe_laneId=traci.vehicle.getLaneID('v.0.0')
        #     if vehicle_id not in leader_ids and traci.vehicle.getLaneID(vehicle_id)==plexe_laneId:
        #
        #         traci.vehicle.setLateralAlignment(traci.vehicle.getTypeID(vehicle_id), False)
        if veh_info[tc.VAR_TYPE] == vtype and sumo_utils.pelxe_falge == 0:
            # print(2)
            a = 1
            # traci.vehicle.changeLaneRelative(vehicle_id, 1, 10)
            # surrounding_vehicles = sumo_utils.get_surrounding_vehicles(vehicle_id, 50)
            # signals = traci.vehicle.getSignals('v.0.0')
            # for surrounding_vehicle in surrounding_vehicles:
            #     traci.vehicle.setSignals(surrounding_vehicle,signals)
        #
        #     sumo_utils.Overtaking(vehicle_id)
        #     sumo_utils.Overtaking(vehicle_id,global_vehicles)
        pos = veh_info[tc.VAR_POSITION]
        longitude, latitude = sumo_utils.xyConversionlatAndLon(sumo_net_instance, pos)
        speed = veh_info[tc.VAR_SPEED]
        vehicle_type = veh_info[tc.VAR_TYPE]
        # 编队状态：0未编队、1编队完成、 2入队中、3 离队中；编队中序号：领队0、跟1、跟2、跟3
        if vehicle_type == '0':
            formationStatus = 1
            vehicle_type = '19'
        else:
            formationStatus = 0
        car = {"id": vehicle_id, "vehicleType": vehicle_type, "longitude": longitude, "latitude": latitude,
               "courseAngle": veh_info[tc.VAR_ANGLE], "acceleration": veh_info[tc.VAR_ACCELERATION],
               "speed": round(speed * 3.6, 2), "distance": round(veh_info[tc.VAR_DISTANCE], 2),
               "time": traci.simulation.getTime(), "originalColor": str(veh_info[tc.VAR_COLOR]),
               "laneNum": veh_info[tc.VAR_LANE_INDEX],
               "formationStatus": formationStatus
               }
        car_list.append(car)
    # data_ts = time.time()
    # print("匝道管控时间戳", ramp_ts, data_ts, data_ts - ramp_ts)
    tls_state = traci.trafficlight.getRedYellowGreenState('gneJ0')
    # tls_state = "g"
    # ts = str(calendar.timegm(time.gmtime()))
    # taskid = random.randint(1, 3)

    key = str(userId) + '_' + str(task_id) + '_' + str(resource)
    result = {"e1FrameParticipant": car_list, "participantNum": len(car_list), "timeStamp": str(start_ts),
              "globalTimeStamp": str(start_ts), "taskid": key, "tlsState": tls_state}
    try:
        if resource == 0:
            producer.send(TRAFFIC_FLOW_TOPIC_WEBGL, value=result, key=key)
        elif resource == 1:
            producer.send(TRAFFIC_FLOW_TOPIC, value=result, key=task_id)
            # # 打开一个文本文件以写入模式（"w"）
            # with open("webgl/track_output.json", "a") as file:
            #     # 通过循环逐行写入数据到文件中:
            #     file.write(json.dumps(result) + "\n")
    except RuntimeError as re:
        print(str(re))
    except AssertionError as ae:
        print(str(ae))


def send_kafka_message(global_vehicles, vtype, sumo_net_instance, traci, userId, task_id, resource, start_ts, producer):
    car_list = list()
    for vehicle_id, veh_info in dict(global_vehicles).items():

        # 编队车辆禁止变道
        # if 'v.0.0' in vehicle_ids:
        #     plexe_laneId=traci.vehicle.getLaneID('v.0.0')
        #     if vehicle_id not in leader_ids and traci.vehicle.getLaneID(vehicle_id)==plexe_laneId:
        #
        #         traci.vehicle.setLateralAlignment(traci.vehicle.getTypeID(vehicle_id), False)
        if veh_info[tc.VAR_TYPE] == vtype and sumo_utils.pelxe_falge == 0:
            # print(2)
            a = 1
            # traci.vehicle.changeLaneRelative(vehicle_id, 1, 10)
            # surrounding_vehicles = sumo_utils.get_surrounding_vehicles(vehicle_id, 50)
            # signals = traci.vehicle.getSignals('v.0.0')
            # for surrounding_vehicle in surrounding_vehicles:
            #     traci.vehicle.setSignals(surrounding_vehicle,signals)
        #
        #     sumo_utils.Overtaking(vehicle_id)
        #     sumo_utils.Overtaking(vehicle_id,global_vehicles)
        pos = veh_info[tc.VAR_POSITION]
        longitude, latitude = sumo_utils.xyConversionlatAndLon(sumo_net_instance, pos)
        speed = veh_info[tc.VAR_SPEED]
        vehicle_type = veh_info[tc.VAR_TYPE]
        # 编队状态：0未编队、1编队完成、 2入队中、3 离队中；编队中序号：领队0、跟1、跟2、跟3
        if vehicle_type == '0':
            formationStatus = 1
            vehicle_type = '19'
        else:
            formationStatus = 0
        car = {"id": vehicle_id, "vehicleType": vehicle_type, "longitude": longitude, "latitude": latitude,
               "courseAngle": veh_info[tc.VAR_ANGLE], "acceleration": veh_info[tc.VAR_ACCELERATION],
               "speed": round(speed * 3.6, 2), "distance": round(veh_info[tc.VAR_DISTANCE], 2),
               "time": traci.simulation.getTime(), "originalColor": str(veh_info[tc.VAR_COLOR]),
               "laneNum": veh_info[tc.VAR_LANE_INDEX],
               "formationStatus": formationStatus
               }
        car_list.append(car)
    # data_ts = time.time()
    # print("匝道管控时间戳", ramp_ts, data_ts, data_ts - ramp_ts)
    tls_state = traci.trafficlight.getRedYellowGreenState('277.276')
    # tls_state = "g"
    # ts = str(calendar.timegm(time.gmtime()))
    # taskid = random.randint(1, 3)

    key = str(userId) + '_' + str(task_id) + '_' + str(resource)
    result = {"e1FrameParticipant": car_list, "participantNum": len(car_list), "timeStamp": str(start_ts),
              "globalTimeStamp": str(start_ts), "taskid": key, "tlsState": tls_state}
    try:
        if resource == 0:
            producer.send(TRAFFIC_FLOW_TOPIC_WEBGL, value=result, key=key)
        elif resource == 1:
            producer.send(TRAFFIC_FLOW_TOPIC, value=result, key=task_id)
            # # 打开一个文本文件以写入模式（"w"）
            # with open("webgl/track_output.json", "a") as file:
            #     # 通过循环逐行写入数据到文件中:
            #     file.write(json.dumps(result) + "\n")
    except RuntimeError as re:
        print(str(re))
    except AssertionError as ae:
        print(str(ae))


def MTF_send_kafka_message(depart_info, global_vehicles, sumo_net_instance, traci, userId, task_id, resource, start_ts,
                           producer):
    car_list = list()
    print("车辆id集合",dict(global_vehicles).keys())
    for vehicle_id, veh_info in dict(global_vehicles).items():
        if vehicle_id in depart_info.keys():
            pos = veh_info[tc.VAR_POSITION]
            longitude, latitude = sumo_utils.xyConversionlatAndLon(sumo_net_instance, pos)
            speed = veh_info[tc.VAR_SPEED]
            vehicle_type = veh_info[tc.VAR_TYPE]
            car = {"id": vehicle_id, "vehicleType": vehicle_type, "longitude": longitude, "latitude": latitude,
                   "courseAngle": veh_info[tc.VAR_ANGLE], "acceleration": veh_info[tc.VAR_ACCELERATION],
                   "speed": round(speed * 3.6, 2), "distance": round(veh_info[tc.VAR_DISTANCE], 2),
                   "time": traci.simulation.getTime(), "originalColor": str(veh_info[tc.VAR_COLOR]),
                   "laneNum": veh_info[tc.VAR_LANE_INDEX]
                   }
            car_list.append(car)

    tls_state = traci.trafficlight.getRedYellowGreenState('694')

    key = str(userId) + '_' + str(task_id) + '_' + str(resource)
    result = {"e1FrameParticipant": car_list, "participantNum": len(car_list), "timeStamp": str(start_ts),
              "globalTimeStamp": str(start_ts), "taskid": key, "tlsState": tls_state}
    try:
        if resource == 0:

            producer.send(MTF_TRAFFIC_FLOW_TOPIC_WEBGL, value=result, key=key)
        elif resource == 1:
            producer.send(TRAFFIC_FLOW_TOPIC, value=result, key=task_id)
    # 打开一个文本文件以写入模式（"w"）
    # with open("webgl/zhulu.json", "a") as file:
    #     # 通过循环逐行写入数据到文件中:
    #     file.write(json.dumps(result) + "\n")

    except RuntimeError as re:
        print(str(re))
    except AssertionError as ae:
        print(str(ae))



def MTF_send_kafka_weather_message(producer,value,userId,task_id,resource):
    key = str(userId) + '_' + str(task_id) + '_' + str(resource)
    try:
        producer.send(MTF_BAD_WEATHER_TOPIC, value=value, key=key)
    except RuntimeError as re:
        print(str(re))
    except AssertionError as ae:
        print(str(ae))



def send_event_message(producer, accident, badWeather, rateLimiting, rampControl, emergencyLane, specialLane,
                       frame_info, task_id):
    trafficEvents = list()
    # 获取当前时间
    now = datetime.datetime.now()

    # 定义所需输出格式
    output_format = '%Y-%m-%d %H:%M:%S'

    # 格式化当前时间
    formatted_time = now.strftime(output_format)
    # 发送消息
    busyAreas = list()
    for accidents_i in accident:
        busyArea = {"type": accidents_i['status'], 'polygons': accidents_i['polygons']}
        busyAreas.append(busyArea)

    if rampControl is not None:
        trafficEvent = {"eventType": '0', "eventLocation": 'p4+10', "date": formatted_time,
                        'busyAreas': [],
                        'serverWeather': []
                        }
        trafficEvents.append(trafficEvent)

    if rateLimiting is not None:
        trafficEvent = {"eventType": '1', "eventLocation": 'p5+10', "date": formatted_time,
                        'busyAreas': [],
                        'serverWeather': []
                        }
        trafficEvents.append(trafficEvent)
    if emergencyLane is not None:
        trafficEvent = {"eventType": '2', "eventLocation": 'p5+10', "date": formatted_time,
                        'busyAreas': [],
                        'serverWeather': []
                        }
        trafficEvents.append(trafficEvent)
    if specialLane is not None:
        trafficEvent = {"eventType": '3', "eventLocation": 'p5+10', "date": formatted_time,
                        'busyAreas': [],
                        'serverWeather': []
                        }
        trafficEvents.append(trafficEvent)
    if accident is not None and len(accident) > 0:
        for accidents_i in accident:
            if accidents_i['status'] == 0:
                lon = accidents_i['areaPoints'][0][0]
                lat = accidents_i['areaPoints'][0][1]
                min_distance, station_info_id = station_util.get_station_number(lon, lat)
                trafficEvent = {"eventType": '5',
                                "eventLocation": str(station_info_id) + '+' + str("{:.2f}".format(min_distance)),
                                "date": formatted_time,
                                'busyAreas': busyAreas,
                                'serverWeather': []
                                }
                trafficEvents.append(trafficEvent)
            else:
                lon = accidents_i['areaPoints'][0][0]
                lat = accidents_i['areaPoints'][0][1]
                min_distance, station_info_id = station_util.get_station_number(lon, lat)
                trafficEvent = {"eventType": '4',
                                "eventLocation": str(station_info_id) + '+' + str("{:.2f}".format(min_distance)),
                                "date": formatted_time,
                                'busyAreas': busyAreas,
                                'serverWeather': []
                                }
                trafficEvents.append(trafficEvent)
    if badWeather is not None and len(badWeather) > 0:
        for badWeather_i in badWeather:
            min_distance, station_info_id = station_util.get_station_number(badWeather_i['lon'], badWeather_i['lat'])
            SituationLL = {"longitude": badWeather_i['lon'], "latitude": badWeather_i['lat']}
            ServerWeather = {"type": badWeather_i['status'], 'situation': SituationLL, 'radius': badWeather_i['radius']}
            trafficEvent = {"eventType": '6',
                            "eventLocation": str(station_info_id) + '+' + str("{:.2f}".format(min_distance)),
                            "date": formatted_time,
                            'busyAreas': [],
                            'serverWeather': ServerWeather
                            }
            trafficEvents.append(trafficEvent)
    # trafficEvent = {"eventType": '5', "eventLocation": 'eventLocation', "date": formatted_time, 'busyAreas': busyAreas,
    #                 'serverWeather': ServerWeathers
    #                 }

    CARoadCombinedEvent = {"taskid": task_id, "date": formatted_time, "trafficData": trafficEvents}
    producer.send(TRAFFIC_EVENT_TOPIC, value=CARoadCombinedEvent, key=task_id)


# 判断编队车辆所在当前的道路
prev_lane = None
my_flag = False
EMERGENCY_LANE_ALLOW_VCLASS = ['emergency', 'authority', 'army']
EXCLUSIVE_LANE_ALLOW_VCLASS = ['custom1']


def plexe_update_lane_access(vehicle_id, traci):
    global prev_lane, my_flag
    # 获取车辆所在的当前道路名称
    road_id = traci.vehicle.getRoadID(vehicle_id)

    # 获取车辆所在的当前车道索引
    lane_index = traci.vehicle.getLaneIndex(vehicle_id)

    # 获取车辆所在的当前车道边缘ID
    lane_edge_id = road_id + '_' + str(lane_index)
    if not my_flag:
        traci.lane.setDisallowed(lane_edge_id, [])
        prev_lane = lane_edge_id
        my_flag = True
    if lane_edge_id != prev_lane and prev_lane is not None:
        traci.lane.setDisallowed(prev_lane, [])
        traci.lane.setAllowed(lane_edge_id, EXCLUSIVE_LANE_ALLOW_VCLASS)
        prev_lane = lane_edge_id


appCarMap = {}


def vehicle_add_HDV_AV_CV(locusQueue, traci, sumo_net_instance, global_vehicles, count_step):
    global appCarMap

    if locusQueue.qsize() > 0:
        vInfos = json.loads(locusQueue.get(block=False))

        # e1FrameParticipants = vehicle_info["e1FrameParticipant"]

        # if len(e1FrameParticipants) > 0:
        for vInfo in vInfos["data"]:
            # e1FrameParticipants里面只存在一个特殊车辆
            # vInfo = e1FrameParticipants[0]
            # print(vInfo)
            vehicle_id = str(vInfo["id"])
            lon = vInfo["lo"]
            lat = vInfo["la"]
            carId = str(vInfo["id"])
            speed = vInfo["speed"] / 3.6
            courseAngle = vInfo["ag"]
            vehicle_type = vInfo["type"]
            # id_list = traci.vehicle.getIDList()

            if vehicle_id in global_vehicles.keys():
                # 背景车流避让真实车流策略
                sumo_utils.background_vehicle_chang_lane(global_vehicles, vehicle_id, traci)
            x, y = sumo_utils.latAndLonConversionXY(sumo_net_instance, {"lon": lon, "lat": lat})

            """
            如果连续3帧特殊车辆都没有出现，则认为特殊车辆已经消失，将特殊车辆从仿真中删除
            """
            deleteList = []
            if carId not in appCarMap.keys():
                appCarMap[carId] = count_step
            else:
                for k, v in appCarMap.items():
                    if count_step - v <= 10 and carId == k:
                        appCarMap[k] = count_step
                    if count_step - appCarMap[k] > 10 and k not in deleteList:
                        deleteList.append(k)
                for delId in deleteList:
                    if str(delId) in global_vehicles.keys():
                        del appCarMap[delId]
                        traci.vehicle.remove(str(delId))
                        # print("车辆消失，删除", carId)

            """
            如果车辆第一次出现，则找到车辆第一次出现位置的路段，添加车辆，同时，使用moveToXY进行位置微调
            如果车辆已经出现，则直接使用moveToXY进行车辆的准确移动
            """
            if vehicle_id not in global_vehicles.keys():
                EdgeID, Pos, LaneIndex = traci.simulation.convertRoad(lon, lat, True)
                routeid = str(uuid.uuid1())
                traci.route.add(routeid, [EdgeID])
                try:
                    if speed >= 0:
                        traci.vehicle.add(vehID=str(carId), routeID=routeid, typeID=str(vehicle_type), depart="now",
                                          departPos=Pos, departSpeed=str(speed))
                    else:
                        traci.vehicle.add(vehID=str(carId), routeID=routeid, typeID=str(vehicle_type), depart="now",
                                          departPos=Pos, departSpeed="random")
                except Exception as e:
                    if "to add already exists" in str(e):
                        traci.vehicle.remove(str(carId))
                    print("车辆已经存在：" + str(e) + str(carId) + " " + str(speed))
                if speed >= 0:
                    traci.vehicle.setSpeed(str(carId), speed)
                traci.vehicle.moveToXY(vehID=str(carId), angle=courseAngle, edgeID="", lane=-1, x=x, y=y,
                                       keepRoute=2)
            else:
                try:
                    traci.vehicle.moveToXY(vehID=str(carId), angle=courseAngle, edgeID="", lane=-1, x=x, y=y,
                                           keepRoute=2)
                except Exception as e:
                    if "to add already exists" in str(e):
                        traci.vehicle.remove(str(carId))
                    print("moveToXY异常：" + str(e) + str(carId) + " " + str(speed))
    # else:
    #     print("locusQueue为空")


def vehicle_add_HDV_AV_CV1(real_vehicle_queue, traci, sumo_net_instance, global_vehicles, count_step):
    global appCarMap

    while not real_vehicle_queue.empty():
        vInfo = real_vehicle_queue.get(block=False)
        # e1FrameParticipants = vehicle_info["e1FrameParticipant"]

        # if len(e1FrameParticipants) > 0:
        if True:
            # e1FrameParticipants里面只存在一个特殊车辆
            # vInfo = e1FrameParticipants[0]
            # print(vInfo)
            vehicle_id = str(vInfo["id"])
            lon = vInfo["lo"]
            lat = vInfo["la"]
            carId = "CV"
            speed = vInfo["speed"] / 3.6
            courseAngle = vInfo["ag"]
            # id_list = traci.vehicle.getIDList()

            if vehicle_id in global_vehicles.keys():
                # 背景车流避让真实车流策略
                sumo_utils.background_vehicle_chang_lane(global_vehicles, vehicle_id, traci)
            x, y = sumo_utils.latAndLonConversionXY(sumo_net_instance, {"lon": lon, "lat": lat})

            """
            如果连续3帧特殊车辆都没有出现，则认为特殊车辆已经消失，将特殊车辆从仿真中删除
            """
            # deleteList = []
            # if vehicle_id not in appCarMap.keys():
            #     appCarMap[vehicle_id] = count_step
            # else:
            #     for k, v in appCarMap.items():
            #         if count_step - v <= 100 and vehicle_id == k:
            #             appCarMap[k] = count_step
            #         if count_step - appCarMap[k] > 100 and k not in deleteList:
            #             deleteList.append(k)
            #     for delId in deleteList:
            #         if str(delId) in global_vehicles.keys():
            #             del appCarMap[delId]
            #             traci.vehicle.remove(str(delId))
            #             print("车辆消失，删除", carId)

            """
            如果车辆第一次出现，则找到车辆第一次出现位置的路段，添加车辆，同时，使用moveToXY进行位置微调
            如果车辆已经出现，则直接使用moveToXY进行车辆的准确移动
            为了避免车辆移动，设置车辆的速度为0
            """
            if vehicle_id not in global_vehicles.keys():
                EdgeID, Pos, LaneIndex = traci.simulation.convertRoad(lon, lat, True)
                routeid = str(uuid.uuid1())
                traci.route.add(routeid, [EdgeID])
                try:
                    if speed >= 0:
                        traci.vehicle.add(vehID=str(vehicle_id), routeID=routeid, typeID=str(carId), depart="now",
                                          departPos=Pos, departSpeed="0")
                    else:
                        traci.vehicle.add(vehID=str(vehicle_id), routeID=routeid, typeID=str(carId), depart="now",
                                          departPos=Pos, departSpeed="0")
                except Exception as e:
                    if "to add already exists" in str(e):
                        traci.vehicle.remove(str(vehicle_id))
                    print("车辆已经存在：" + str(e) + str(vehicle_id) + " " + str(speed))
                if speed >= 0:
                    traci.vehicle.setSpeed(str(vehicle_id), 0)
                traci.vehicle.moveToXY(vehID=str(vehicle_id), angle=courseAngle, edgeID="", lane=-1, x=x, y=y,
                                       keepRoute=2)
            else:
                try:
                    traci.vehicle.setSpeed(str(vehicle_id), 0)
                    traci.vehicle.moveToXY(vehID=str(vehicle_id), angle=courseAngle, edgeID="", lane=-1, x=x, y=y,
                                           keepRoute=2)
                except Exception as e:
                    if "to add already exists" in str(e):
                        traci.vehicle.remove(str(vehicle_id))
                    print("moveToXY异常：" + str(e) + str(vehicle_id) + " " + str(speed))
